package bma.common.netty.tester;

import java.net.InetSocketAddress;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

import bma.common.langutil.log.LogPrinter;
import bma.common.langutil.log.LogPrinter.LEVEL;
import bma.common.langutil.pipeline.CommonPipelineBuilder;
import bma.common.netty.NettyChannelPipeline;
import bma.common.netty.handler.ChannelHandlerLog;
import bma.common.netty.handler.ChannelHandlerLog.TYPE;

public class NettyServerTester {

	final org.slf4j.Logger log = org.slf4j.LoggerFactory
			.getLogger(NettyServerTester.class);

	private CommonPipelineBuilder<ChannelHandler> serverBuilder;

	public CommonPipelineBuilder<ChannelHandler> getServerBuilder() {
		return serverBuilder;
	}

	public void setServerBuilder(
			CommonPipelineBuilder<ChannelHandler> serverBuilder) {
		this.serverBuilder = serverBuilder;
	}

	protected ChannelPipelineFactory serverFactory() {
		return new ChannelPipelineFactory() {

			@Override
			public ChannelPipeline getPipeline() throws Exception {
				ChannelPipeline p = Channels.pipeline(); // Note the static
															// import.
				if (serverBuilder != null) {
					serverBuilder.buildPipeline(new NettyChannelPipeline(p));
				}
				p.addFirst("log", new ChannelHandlerLog(new LogPrinter(log,
						LEVEL.DEBUG), TYPE.ALL, 1024 * 1000));
				return p;
			}
		};
	}

	private Channel serverChannel;

	public Channel start(int localPort, long time) throws Exception {

		System.err.println("start ServerTester *:" + localPort);

		// Configure the bootstrap.
		Executor executor = Executors.newCachedThreadPool();

		ServerBootstrap sb = new ServerBootstrap(
				new NioServerSocketChannelFactory(executor, executor));
		sb.setPipelineFactory(serverFactory());
		serverChannel = sb.bind(new InetSocketAddress(localPort));

		return serverChannel;
	}

	public void close() {
		if (serverChannel != null) {
			serverChannel.close();
		}
	}
}
